package com.gaogzhen.aqs;

import com.gaogzhen.util.GenericDao;

import java.util.*;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * @author Administrator
 * @date 2022-11-30 07:48
 */
public class TestGenericDao {
    public static void main(String[] args) {
        GenericDao dao = new GenericDaoCached();
        System.out.println("=============>查询");
        String sql = "select * from emp where empno = ?";
        int empno = 7369;
        Emp emp = dao.queryOne(Emp.class, sql, empno);
        System.out.println(emp);
        emp = dao.queryOne(Emp.class, sql, empno);
        System.out.println(emp);

        System.out.println("================>更新");
        String sqlUpdate = "update emp set sal = ? where empno = ?";
        dao.update(sqlUpdate, 1600, empno);
        emp = dao.queryOne(Emp.class, sql, empno);
        System.out.println(emp);
    }

    static class GenericDaoCached extends GenericDao {
        private GenericDao dao = new GenericDao();
        private Map<SqlPair, Object> map = new HashMap<>();
        private ReentrantReadWriteLock rw = new ReentrantReadWriteLock();

        @Override
        public <T> List<T> queryList(Class<T> beanClass, String sql, Object... args) {
            return dao.queryList(beanClass, sql, args);
        }

        @Override
        public <T> T queryOne(Class<T> beanClass, String sql, Object... args) {
            // 先从缓存中找，找到直接返回
            SqlPair key = new SqlPair(sql, args);
            ;
            rw.readLock().lock();
            try {
                T value = (T) map.get(key);
                if (value != null) {
                    return value;
                }
            } finally {
                rw.readLock().unlock();
            }
            rw.writeLock().lock();
            try {
                // 多个线程
                T value = (T) map.get(key);
                if (value == null) {
                    // 缓存中没有，查询数据库
                    value = dao.queryOne(beanClass, sql, args);
                    map.put(key, value);
                }
                return value;
            } finally {
                rw.writeLock().unlock();
            }
        }

        @Override
        public int update(String sql, Object... args) {
            rw.writeLock().lock();
            try {
                // 先更新库
                int update = dao.update(sql, args);
                // 清空缓存
                map.clear();
                return update;
            } finally {
                rw.writeLock().unlock();
            }
        }

        class SqlPair {
            private String sql;
            private Object[] args;

            public SqlPair(String sql, Object[] args) {
                this.sql = sql;
                this.args = args;
            }

            @Override
            public boolean equals(Object o) {
                if (this == o) {
                    return true;
                }
                if (o == null || getClass() != o.getClass()) {
                    return false;
                }
                SqlPair sqlPair = (SqlPair) o;
                return Objects.equals(sql, sqlPair.sql) &&
                        Arrays.equals(args, sqlPair.args);
            }

            @Override
            public int hashCode() {
                int result = Objects.hash(sql);
                result = 31 * result + Arrays.hashCode(args);
                return result;
            }
        }
    }
}
